package com.coin900.coin.server.fu.ctrl;

import com.coin900.coin.base.AjaxResponse;
import com.coin900.coin.base.CoinConstants;
import com.coin900.coin.base.FuConstants;
import com.coin900.coin.base.utils.JavaSmsApi;
import com.coin900.coin.base.utils.ValidatorUtil;
import com.coin900.coin.persist.coin.CoinMailVerifyRecordVO;
import com.coin900.coin.persist.fu.FuUserVO;
import com.coin900.coin.server.BaseController;
import com.coin900.coin.server.fu.form.RegistForm;
import com.coin900.coin.service.coin.ICoinMailVerifyRecordService;
import com.coin900.coin.service.fu.IFuUserService;
import com.value.exception.BusinessException;
import com.value.utils.Md5Encoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import sun.misc.BASE64Encoder;

import javax.annotation.Resource;
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.servlet.FilterRegistration;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author zhangyou
 * @date 2017/11/20
 */
@RestController
public class IndexCtrl extends BaseController {

    /**
     * 验证码过期时间 15 min ，15 * 60 = 900
     */
    private static int EXPIRETIME = 900;
    /**
     * 验证码重新发送最小时间 2 min, 900 - 2 * 60 = 780
     */
    private static int CODE_RESEND = 780;


    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView indexSite(HttpServletRequest request,
                                  HttpServletResponse response) {
        Map<String, ? extends FilterRegistration> filterRegistrations =
                request.getServletContext().getFilterRegistrations();
        System.out.println(filterRegistrations);
        ModelAndView modelAndView = super.buildView(request, "index");
        return modelAndView;
    }


    /**
     * 发送绑定手机号短信验证码
     *
     * @param mobile
     * @param request
     * @return
     */
    @RequestMapping(value = "/bind-mobile-code", method = RequestMethod.GET)
    public Object sendCode(@RequestParam String mobile,
                           HttpServletRequest request) {

        if (!ValidatorUtil.checkMobile(mobile)) {
            throw new BusinessException("请输入正确的手机号");
        }

        String code = this.generateCode();
        String key = CoinConstants.COIN_SMS_CODE_MOBILE_BIND + mobile;
        if (this.redisTemplate.getExpire(key) < CODE_RESEND) {
            try {
                /****** 配置短信模板 ******/
                String text = "您的验证码是" + code;
                JavaSmsApi.sendSms(text, mobile);
            } catch (IOException e) {
                e.printStackTrace();
            }
            this.redisTemplate.opsForValue().set(key, code);
            this.redisTemplate.expire(key, EXPIRETIME, TimeUnit.SECONDS);
            return "success";
        } else {
            throw new BusinessException("验证码已经发送");
        }
    }

    /**
     * 绑定手机号
     *
     * @param code
     * @param request
     * @return
     */
    @RequestMapping(value = "/bind-mobile", method = RequestMethod.GET)
    public ModelAndView securityCenter(@RequestParam String code,
                                       @RequestParam String mobile,
                                       HttpServletRequest request) {

        FuUserVO user = super.getUser();
        String redisCode = (String) this.redisTemplate.opsForValue().get(CoinConstants.COIN_SMS_CODE_MOBILE_BIND + mobile);
        if (!code.equals(redisCode)) {
            throw new BusinessException("验证码错误");
        } else {
            // 验证成功,绑定手机号
            user.setMobile(mobile);
            user.setMoblieStatus(1);
            this.userService.updateFuUser(user);
        }

        return null;
    }

    /**
     * 跳转到注册页面
     *
     * @param viewType
     * @param request
     * @return
     */
    @RequestMapping(value = "/registration", method = RequestMethod.GET)
    public ModelAndView registration(String viewType,
                                     HttpServletRequest request) {
        if (FuConstants.FU_PAGE.equals(viewType)) {
            ModelAndView modelAndView = super.buildView(request, "project/registration");
            return modelAndView;
        }
        return null;
    }

    /**
     * 用户注册
     *
     * @param registForm
     * @param request
     * @return
     */
    @RequestMapping(value = "/registration", method = RequestMethod.POST)
    public ModelAndView register(@RequestBody RegistForm registForm,
                                 HttpServletRequest request) {

        AjaxResponse response = super.buildAjaxResponse(request);
        Map<String, Object> params = new HashMap<>();

        String password = registForm.getPassword();
        if (!password.equals(registForm.getRepassword())) {
            throw new BusinessException("密码不一致");
        }

        String email = registForm.getEmail();
        if (!ValidatorUtil.isEmail(email)) {
            throw new BusinessException("请输入正确的邮箱");
        }
        params.put("username", email);
        params.put("userType", FuConstants.FU_USER_TYPE_TOKENOK);
        List<FuUserVO> fuUserVOS = this.userService.loadFuUser(params);
        if (!fuUserVOS.isEmpty()) {
            throw new BusinessException("邮箱已注册");
        }

        FuUserVO userVO = new FuUserVO();
        // 用户名默认为邮箱
        userVO.setUsername(email);
        userVO.setEmail(email);
        userVO.setPassword(Md5Encoder.generateCode(password));
        userVO.setCreatedBy(0L);
        userVO.setCreatedDate(new Date());
        // 直接注册，用户为众投用户
        userVO.setUserType(FuConstants.FU_USER_TYPE_TOKENOK);
        String wlink = registForm.getWlink();
        Long shareUserId = null;

        if (wlink != null) {
            DESKeySpec keySpec = null;
            try {
                keySpec = new DESKeySpec(CoinConstants.INVITE_SERCET_KEY.getBytes());
                SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("des");
                SecretKey secretKey = keyFactory.generateSecret(keySpec);
                Cipher cipher = Cipher.getInstance("des");
                cipher.init(Cipher.DECRYPT_MODE, secretKey, new SecureRandom());

                byte[] wlinkBytes = Base64.getDecoder().decode(wlink);
                byte[] plainData = cipher.doFinal(wlinkBytes);
                String secretUserId = new String(plainData);
                shareUserId = Long.parseLong(secretUserId);
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            } catch (InvalidKeySpecException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            }
        }


        if (shareUserId == null) {
            this.userService.insertFuUser(userVO);
        } else {
            this.userService.insertFuUser(userVO, shareUserId);
        }
        /***** 发送激活邮件 *****/
        CoinMailVerifyRecordVO coinMailVerifyRecordVO = new CoinMailVerifyRecordVO();
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MINUTE, 30);
        Date time = calendar.getTime();
        coinMailVerifyRecordVO.setExpiryTime(time);
        coinMailVerifyRecordVO.setUserId(userVO.getId());
        coinMailVerifyRecordVO.setMailBox(userVO.getEmail());
        coinMailVerifyRecordVO.setCMInfor(userVO);
        try {
            mailVerifyRecordService.insertCoinMailVerifyRecord(coinMailVerifyRecordVO);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response.getMav();
    }


    /**
     * 校验手机号是否重复
     *
     * @param mobile
     * @param request
     * @return
     */
    @RequestMapping(path = "/regist/check_mobile", method = RequestMethod.GET)
    public ModelAndView getRegister(@RequestParam String mobile,
                                    HttpServletRequest request) {

        AjaxResponse response = super.buildAjaxResponse(request);
        if (!ValidatorUtil.checkMobile(mobile)) {
            throw new BusinessException("请输入正确的手机号");
        }

        Map<String, Object> params = new HashMap<>();
        params.put("mobile", mobile);
        List<FuUserVO> fuUserVOS = this.userService.loadFuUser(params);
        if (!fuUserVOS.isEmpty()) {
            throw new BusinessException("手机号已注册");
        }

        return response.getMav();
    }

    /**
     * 校验用户名
     * 3-6 位文字、字母或数字 && 不重复
     *
     * @param username
     * @param request
     * @return
     */
    @RequestMapping(path = "/regist/check_username", method = RequestMethod.GET)
    public ModelAndView checkUserName(@RequestParam String username,
                                      HttpServletRequest request) {

        AjaxResponse response = super.buildAjaxResponse(request);
        if (ValidatorUtil.checkUsername(username)) {
            throw new BusinessException("用户名格式错误");
        }
        Map<String, Object> params = new HashMap<>();
        params.put("username", username);
        List<FuUserVO> fuUserVOS = this.userService.loadFuUser(params);
        if (!fuUserVOS.isEmpty()) {
            throw new BusinessException("用户名已存在");
        }

        return response.getMav();
    }

    /**
     * 获取 6 位随机验证码
     *
     * @return
     */
    public String generateCode() {
        String code = "";
        for (int i = 0; i < 6; i++) {
            code = code + String.valueOf((int) Math.floor(Math.random() * 9 + 1));
        }
        return code;
    }

    @Autowired
    private ICoinMailVerifyRecordService mailVerifyRecordService;
    @Autowired
    private IFuUserService userService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
}
